import sys
from fastapi import APIRouter, Request, Response, HTTPException
from fastapi.responses import JSONResponse
import httpx
import structlog
from typing import Dict, Any, Optional, List
from pydantic import BaseModel
import json
from datetime import datetime, timedelta
import time
import collections

# 创建logger
logger = structlog.get_logger(__name__)
router = APIRouter(tags=["Gateway"])

# 获取服务实例
from app.services.service_instances import service_discovery, load_balancer

# 内存存储 - 请求统计数据
request_stats = {
    "hourly": collections.defaultdict(lambda: {"requests": 0, "errors": 0}),
    "recent": collections.deque(maxlen=100)
}


def record_request_stats(request: Request, status_code: int, response_time: float):
    """记录请求统计"""
    current_hour = datetime.now().strftime("%Y-%m-%d %H:00")
    request_stats["hourly"][current_hour]["requests"] += 1
    if status_code >= 400:
        request_stats["hourly"][current_hour]["errors"] += 1

    service_name = request.path_params.get("service_name", "unknown")
    path = request.path_params.get("path", "")

    request_record = {
        "time": datetime.now().isoformat(),
        "method": request.method,
        "service_name": service_name,
        "path": path,
        "status_code": status_code,
        "client_ip": request.client.host,
        "request_id": getattr(request.state, "request_id", None),
        "response_time": round(response_time, 3)
    }
    request_stats["recent"].appendleft(request_record)


class SUNARequestModel(BaseModel):
    """SUNA后端请求模型"""
    method: str
    path: str
    headers: Dict[str, str]
    query_params: Dict[str, Any]
    body: Optional[Dict[str, Any]] = None
    request_id: Optional[str] = None
    user: Optional[Dict[str, Any]] = None


@router.get("/{service_name}/{path:path}")
@router.post("/{service_name}/{path:path}")
@router.put("/{service_name}/{path:path}")
@router.delete("/{service_name}/{path:path}")
@router.patch("/{service_name}/{path:path}")
@router.options("/{service_name}/{path:path}")
@router.head("/{service_name}/{path:path}")
async def proxy_request(service_name: str, path: str, request: Request):
    """代理请求到指定服务"""

    start_time = time.time()
    request_id = getattr(request.state, 'request_id', 'unknown')
    user_id = getattr(request.state, 'user', {}).get('sub', 'anonymous')

    # 🔍 拦截前的路径信息
    original_path = str(request.url.path)
    original_full_url = str(request.url)

    logger.info(f"[{request_id[:8]}] {request.method} {service_name}/{path}")
    # print(f"   📍 拦截前: {original_path}")
    logger.info(f"用户: {user_id}")

    try:
        # 获取服务实例
        service = load_balancer.get_service_instance(service_name)
        if not service or not service.is_healthy:
            logger.error(f"服务不可用: {service_name}")
            raise HTTPException(status_code=503, detail=f"Service '{service_name}' unavailable")

        # 构建目标URL
        service_base_url = service.url.rstrip('/')
        target_path = path.lstrip('/')
        target_url = f"{service_base_url}/{target_path}"

        if request.query_params:
            target_url += f"?{request.query_params}"

        # 🎯 转发后的路径信息
        logger.info(f"路径映射: /{service_name}/{path} → /{target_path}")
        logger.info("=" * 60)

        # 准备headers
        skip_headers = {'host', 'content-length', 'connection', 'keep-alive'}
        headers = {
            name: value for name, value in request.headers.items()
            if name.lower() not in skip_headers
        }

        # 添加Gateway headers
        if hasattr(request.state, 'request_id'):
            headers["X-Request-ID"] = request.state.request_id
        if hasattr(request.state, 'user'):
            headers["X-User-ID"] = request.state.user.get("sub", "")
            headers["X-User-Email"] = request.state.user.get("email", "")

        # 处理请求体
        content_to_send = None
        if request.method in ["POST", "PUT", "PATCH"]:
            raw_body = await request.body()
            if raw_body:
                try:
                    body_str = raw_body.decode('utf-8')
                    body_dict = json.loads(body_str) if body_str.strip() else {}
                    print(f"   📦 请求体: {len(raw_body)} bytes")
                except json.JSONDecodeError:
                    body_dict = {"raw_data": body_str if 'body_str' in locals() else str(raw_body)}
                    print(f"   📦 非JSON请求体: {len(raw_body)} bytes")
                except Exception:
                    body_dict = {"raw_data": "binary_data", "size": len(raw_body)}
                    print(f"   📦 二进制请求体: {len(raw_body)} bytes")

                # 构建SUNA请求
                suna_request = SUNARequestModel(
                    method=request.method,
                    path=path,
                    headers=headers,
                    query_params=dict(request.query_params),
                    body=body_dict,
                    request_id=getattr(request.state, 'request_id', None),
                    user=getattr(request.state, 'user', None)
                )

                suna_json = suna_request.model_dump_json()
                content_to_send = suna_json.encode('utf-8')
                headers["Content-Type"] = "application/json"
                headers["Content-Length"] = str(len(content_to_send))

        # 发送请求到后端
        timeout_config = httpx.Timeout(connect=5.0, read=service.timeout, write=10.0)

        async with httpx.AsyncClient(timeout=timeout_config, follow_redirects=True) as client:
            if content_to_send:
                response = await client.request(
                    method=request.method, url=target_url,
                    headers=headers, content=content_to_send
                )
            else:
                response = await client.request(
                    method=request.method, url=target_url, headers=headers
                )

        # 处理响应
        response_time = time.time() - start_time
        response_headers = {
            k: v for k, v in response.headers.items()
            if k.lower() not in ['content-encoding', 'transfer-encoding', 'content-length']
        }

        # 📊 请求完成日志
        logger.info(f"{response.status_code} | {response_time * 1000:.1f}ms | {len(response.content)} bytes")

        # 记录统计
        record_request_stats(request, response.status_code, response_time)

        return Response(
            content=response.content,
            status_code=response.status_code,
            headers=response_headers
        )

    except httpx.TimeoutException:
        response_time = time.time() - start_time
        logger.error(f"   ⏰ 超时 | {response_time * 1000:.1f}ms")
        record_request_stats(request, 504, response_time)
        raise HTTPException(status_code=504, detail="Service timeout")

    except httpx.ConnectError:
        response_time = time.time() - start_time
        logger.error(f"   🔌 连接失败 | {response_time * 1000:.1f}ms")
        record_request_stats(request, 503, response_time)
        raise HTTPException(status_code=503, detail="Service connection error")

    except HTTPException:
        response_time = time.time() - start_time
        record_request_stats(request, 500, response_time)
        raise

    except Exception as e:
        response_time = time.time() - start_time
        logger.error(f"   💥 异常: {type(e).__name__} - {str(e)} | {response_time * 1000:.1f}ms")
        record_request_stats(request, 500, response_time)
        raise HTTPException(status_code=500, detail=f"Gateway error: {str(e)}")


@router.get("/services")
async def get_services_status():
    """获取所有服务的状态"""
    return service_discovery.get_service_status()


@router.get("/services/{service_name}")
async def get_service_status(service_name: str):
    """获取指定服务的状态"""
    service = service_discovery.get_service(service_name)
    if not service:
        raise HTTPException(status_code=404, detail=f"Service '{service_name}' not found")

    return {
        "name": service.name,
        "url": service.url,
        "is_healthy": service.is_healthy,
        "last_check": service.last_check.isoformat() if service.last_check else None,
        "response_time": f"{service.response_time:.2f}ms",
        "consecutive_failures": service.consecutive_failures
    }


@router.get("/stats/request-trend")
async def get_request_trend():
    """获取请求趋势数据"""
    now = datetime.now()
    trend_data = []

    for i in range(24):
        hour = (now - timedelta(hours=i)).strftime("%Y-%m-%d %H:00")
        stats = request_stats["hourly"].get(hour, {"requests": 0, "errors": 0})
        trend_data.append({
            "hour": hour,
            "requests": stats["requests"],
            "errors": stats["errors"]
        })

    trend_data.sort(key=lambda x: x["hour"])
    return {
        "labels": [item["hour"] for item in trend_data],
        "requests": [item["requests"] for item in trend_data],
        "errors": [item["errors"] for item in trend_data]
    }


@router.get("/requests/recent")
async def get_recent_requests(limit: int = 20):
    """获取最近的请求记录"""
    limit = min(limit, 100)
    return list(request_stats["recent"])[:limit]


@router.get("/stats/summary")
async def get_stats_summary():
    """获取统计摘要"""
    total_requests = sum(
        stats["requests"] for stats in request_stats["hourly"].values()
    )
    total_errors = sum(
        stats["errors"] for stats in request_stats["hourly"].values()
    )

    # 计算最近1小时的数据
    current_hour = datetime.now().strftime("%Y-%m-%d %H:00")
    recent_stats = request_stats["hourly"].get(current_hour, {"requests": 0, "errors": 0})

    return {
        "total_requests": total_requests,
        "total_errors": total_errors,
        "error_rate": (total_errors / total_requests * 100) if total_requests > 0 else 0,
        "recent_hour": {
            "requests": recent_stats["requests"],
            "errors": recent_stats["errors"]
        },
        "services": service_discovery.get_service_status()
    }